package com.android.support.jhf.iphonetreeview;

import java.util.List;

import com.android.support.jhf.R;
import com.android.support.jhf.debug.DebugLog;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ScrollView;
import android.widget.SectionIndexer;
import android.widget.TextView;
import android.widget.AbsListView.LayoutParams;

public class IphoneTreeView extends ExpandableListView implements
		AbsListView.OnScrollListener {

	private static final int MAX_ALPHA = 255;

	private PinnedHeaderAdapter mPinnedHeaderAdapter;
	private ExpandableListAdapter mExpandableListAdapter;
	/**
	 * 用于在列表头显示的 View,mHeaderViewVisible 为 true 才可见
	 */
	private View mHeaderView;
	private Context mContext;
	/**
	 * 列表头是否可见
	 */
	private boolean mHeaderViewVisible;
	private int mHeaderViewWidth;
	private int mHeaderViewHeight;

	private float mDownX;
	private float mDownY;

	private int mOldState = -1;

	private int mIndicatorGroupId = -1;
	private int mIndicatorGroupHeight;
	private int mShowHeight = 0;

	private boolean mIsFastScrollEnabled = false;
	private IndexScroller mScroller = null;
	private GestureDetector mGestureDetector = null;

	public IphoneTreeView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	public IphoneTreeView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public IphoneTreeView(Context context) {
		super(context);
		init(context);
	}

	@Override
	public boolean isFastScrollEnabled() {
		return mIsFastScrollEnabled;
	}

	@Override
	public void setFastScrollEnabled(boolean enabled) {
		mIsFastScrollEnabled = enabled;
		if (mIsFastScrollEnabled) {
			if (mScroller == null)
				mScroller = new IndexScroller(getContext(), this);
		} else {
			if (mScroller != null) {
				mScroller.hide();
				mScroller = null;
			}
		}
	}

	/**
	 * 用来设置固定在列表上方的头，一般就是group
	 * 
	 * @param view
	 * @param height
	 */
	private void setHeaderView(View view) {
		mHeaderView = view;

		AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
				ViewGroup.LayoutParams.FILL_PARENT,
				ViewGroup.LayoutParams.WRAP_CONTENT);
		view.setLayoutParams(lp);
		if (mHeaderView != null) {
			setFadingEdgeLength(0);
		}
		requestLayout();
	}

	private void init(Context context) {
		mContext = context;
		// setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
	}

	private void registerListener() {
		setOnScrollListener(this);
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {

		if (mScroller != null && mScroller.onTouchEvent(ev)) {
			return true;
		}

		return super.onInterceptTouchEvent(ev);
	}

	/**
	 * 如果 HeaderView 是可见的 , 此函数用于判断是否点击了 HeaderView, 并对做相应的处理 , 因为 HeaderView
	 * 是画上去的 , 所以设置事件监听是无效的 , 只有自行控制 .
	 */
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		// Intercept ListView's touch event
		if (mScroller != null && mScroller.onTouchEvent(ev)) {
			return true;
		} else {
			if (mHeaderViewVisible) {
				switch (ev.getAction()) {
				case MotionEvent.ACTION_DOWN: {
					mDownX = ev.getX();
					mDownY = ev.getY();
					if (mDownX <= mHeaderViewWidth
							&& mDownY <= mHeaderViewHeight) {
						return true;
					}
					break;
				}
				case MotionEvent.ACTION_UP: {
					float x = ev.getX();
					float y = ev.getY();
					float offsetX = Math.abs(x - mDownX);
					float offsetY = Math.abs(y - mDownY);
					// 如果 HeaderView 是可见的 , 点击在 HeaderView 内 , 那么触发
					// headerClick()
					if (x <= mHeaderViewWidth && y <= mHeaderViewHeight
							&& offsetX <= mHeaderViewWidth
							&& offsetY <= mHeaderViewHeight) {
						if (mHeaderView != null) {
							headerViewClick();
						}
						return true;
					}
					break;
				}
				case MotionEvent.ACTION_MOVE: {
					break;
				}
				default:
					break;
				}
			}
		}

		if (mGestureDetector == null) {
			mGestureDetector = new GestureDetector(getContext(),
					new GestureDetector.SimpleOnGestureListener() {

						@Override
						public boolean onFling(MotionEvent e1, MotionEvent e2,
								float velocityX, float velocityY) {
							// If fling happens, index bar shows
							if (null != mScroller)
								mScroller.show();
							return super.onFling(e1, e2, velocityX, velocityY);
						}

					});
		}
		mGestureDetector.onTouchEvent(ev);

		return super.onTouchEvent(ev);
	}

	@Override
	public void setAdapter(ExpandableListAdapter adapter) {
		super.setAdapter(adapter);
		mPinnedHeaderAdapter = (PinnedHeaderAdapter) adapter;
		mExpandableListAdapter = (ExpandableListAdapter) adapter;

		if (PinnedHeaderAdapter.ALL_GROUP_EXPAND_NO_CLICK == mPinnedHeaderAdapter
				.getPinnedHeaderState(0, 0)) {
			for (int i = 0; i < mExpandableListAdapter.getGroupCount(); i++) {
				this.expandGroup(i);
			}
		}

		registerListener();

		if (mScroller != null) {
			mScroller.setAdapter((PinnedHeaderAdapter) adapter);
		}

		setHeaderView(mPinnedHeaderAdapter.getPinnedHeadView());
	}

	@Override
	public boolean performItemClick(View v, int position, long id) {

		long pos = getExpandableListPosition(position);
		int positionGroup = ExpandableListView.getPackedPositionGroup(pos);
		int positionType = ExpandableListView.getPackedPositionType(pos);

		if (PinnedHeaderAdapter.ALL_GROUP_EXPAND_NO_CLICK == mPinnedHeaderAdapter
				.getPinnedHeaderState(0, 0)) {
			if (ExpandableListView.PACKED_POSITION_TYPE_GROUP == positionType) {
				return true;
			}
		}

		boolean flag = super.performItemClick(v, position, id);

		if (ExpandableListView.PACKED_POSITION_TYPE_GROUP == positionType) {
			this.setSelectedGroup(positionGroup);
		}

		return flag;
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		if (mScroller != null)
			mScroller.onSizeChanged(w, h, oldw, oldh);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		if (mHeaderView != null) {
			measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);
			mHeaderViewWidth = mHeaderView.getMeasuredWidth();
			mHeaderViewHeight = mHeaderView.getMeasuredHeight();
		}
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);

		if (null == mPinnedHeaderAdapter || null == mExpandableListAdapter) {
			return;
		}

		final long flatPostion = getExpandableListPosition(getFirstVisiblePosition());
		final int groupPos = ExpandableListView
				.getPackedPositionGroup(flatPostion);
		final int childPos = ExpandableListView
				.getPackedPositionChild(flatPostion);
		int state = mPinnedHeaderAdapter.getPinnedHeaderState(groupPos,
				childPos);
		if (mHeaderView != null && mPinnedHeaderAdapter != null
				&& state != mOldState) {
			mOldState = state;
			mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
		}
		configureHeaderView(groupPos, childPos);
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {
		super.dispatchDraw(canvas);
		/**
		 * calculate point (0,0)
		 */
		int npos = this.pointToPosition(0, 0);
		if (npos != AdapterView.INVALID_POSITION) {

			final long flatPos = getExpandableListPosition(npos);
			int groupPosition = ExpandableListView
					.getPackedPositionGroup(flatPos);
			int childPosition = ExpandableListView
					.getPackedPositionChild(flatPos);

			configureHeaderView(groupPosition, childPosition);

			if (childPosition == AdapterView.INVALID_POSITION) {// 用来获取group的高度
				View groupView = this.getChildAt(npos
						- this.getFirstVisiblePosition());// 获取第0个
				mIndicatorGroupHeight = groupView.getHeight();
			}

			// get an error data, so return now
			if (mIndicatorGroupHeight == 0) {
				return;
			}
			// update the data of indicator group view
			if (groupPosition != mIndicatorGroupId) {
				mExpandableListAdapter.getGroupView(groupPosition,
						this.isGroupExpanded(groupPosition), null, null);
				mIndicatorGroupId = groupPosition;
			}
			if (mIndicatorGroupId == -1) {
				return;
			}

			/**
			 * calculate point (0,mIndicatorGroupHeight)
			 */
			mShowHeight = mIndicatorGroupHeight;
			int nEndPos = this.pointToPosition(0, mIndicatorGroupHeight);
			if (nEndPos != AdapterView.INVALID_POSITION) {
				long pos = this.getExpandableListPosition(nEndPos);
				int groupPos = ExpandableListView.getPackedPositionGroup(pos);
				if (groupPos != mIndicatorGroupId) {
					View viewNext = this.getChildAt(nEndPos
							- this.getFirstVisiblePosition());
					mShowHeight = viewNext.getTop();
				}
			}
		}

		Canvas tempCanvas = canvas;

		if (mHeaderViewVisible) {
			canvas.translate(0, -(mIndicatorGroupHeight - mShowHeight));
			drawChild(canvas, mHeaderView, getDrawingTime());

			// Overlay index bar
			if (mScroller != null) {
				tempCanvas.translate(0, (mIndicatorGroupHeight - mShowHeight));
			}
		} else {
			tempCanvas.translate(0, 0);
		}
		mScroller.draw(tempCanvas);

	}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		final long flatPos = getExpandableListPosition(firstVisibleItem);
		int groupPosition = ExpandableListView.getPackedPositionGroup(flatPos);
		int childPosition = ExpandableListView.getPackedPositionChild(flatPos);

		configureHeaderView(groupPosition, childPosition);
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {

	}

	/**
	 * 点击 HeaderView 触发的事件
	 */
	private void headerViewClick() {
		if (PinnedHeaderAdapter.ALL_GROUP_EXPAND_NO_CLICK == mPinnedHeaderAdapter
				.getPinnedHeaderState(0, 0)) {
			return;
		}
		long packedPosition = getExpandableListPosition(this
				.getFirstVisiblePosition());
		int groupPosition = ExpandableListView
				.getPackedPositionGroup(packedPosition);
		if (!this.expandGroup(groupPosition)) {
			this.collapseGroup(groupPosition);
		}
		this.setSelectedGroup(groupPosition);
	}

	private void configureHeaderView(int groupPosition, int childPosition) {
		if (mHeaderView == null
				|| mPinnedHeaderAdapter == null
				|| ((ExpandableListAdapter) mPinnedHeaderAdapter)
						.getGroupCount() == 0) {
			return;
		}

		int state = mPinnedHeaderAdapter.getPinnedHeaderState(groupPosition,
				childPosition);
		switch (state) {
		case PinnedHeaderAdapter.PINNED_HEADER_GONE: {
			mHeaderViewVisible = false;
			break;
		}

		case PinnedHeaderAdapter.PINNED_HEADER_VISIBLE: {

			mPinnedHeaderAdapter.configurePinnedHeader(mHeaderView,
					groupPosition, childPosition, MAX_ALPHA);
			if (mHeaderView.getTop() != 0) {
				mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
			}

			if (true == this.isGroupExpanded(groupPosition)) {
				mHeaderViewVisible = true;
			} else {
				mHeaderViewVisible = false;
			}

			break;
		}
		case PinnedHeaderAdapter.ALL_GROUP_EXPAND_NO_CLICK: {
			mPinnedHeaderAdapter.configurePinnedHeader(mHeaderView,
					groupPosition, childPosition, MAX_ALPHA);
			if (mHeaderView.getTop() != 0) {
				mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
			}

			mHeaderViewVisible = true;

			break;
		}
		default:
			break;
		}
	}

}